package com.gccloud.design.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.gccloud.design.dao.SdFormActionConfigDao;
import com.gccloud.design.dto.SdFormActionConfDto;
import com.gccloud.design.dto.SdFormConfigDto;
import com.gccloud.design.entity.SdFormActionConfEntity;
import com.gccloud.design.entity.SdFormFlowRepoBindEntity;
import com.gccloud.design.entity.SdRepoLimitTimeEntity;
import com.gccloud.design.entity.SdRepoParticipantConfEntity;
import com.gccloud.design.feign.BwpOperDockingClient;
import com.gccloud.design.service.SdFormConfigService;
import com.gccloud.design.service.SdParticipantConfService;
import com.gccloud.design.service.SdRepoTimeLimitService;
import com.gccloud.starter.common.exception.GlobalException;
import com.gccloud.starter.common.vo.R;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author wu.yumin
 * @version 1.0.0
 * @Description 表单配置实现
 * @date 2021/6/23 10:12
 */
@Slf4j
@Service
public class SdFormActionConfigServiceImpl extends ServiceImpl<SdFormActionConfigDao, SdFormActionConfEntity> implements SdFormConfigService {

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    @Resource
    private SdParticipantConfService sdParticipantConfService;
    @Resource
    private SdRepoTimeLimitService sdRepoTimeLimitService;
    @Resource
    private BwpOperDockingClient bwpOperDockingClient;

    @Override
    public List<SdFormActionConfDto> queryActionsByFormId(Long formId) {
        return this.baseMapper.getActionByFormId(formId);
    }

    @Override
    public boolean saveFormAction(List<SdFormActionConfEntity> list) {
        for (SdFormActionConfEntity entity:list) {
            entity.setShardingId(0);
            entity.setDelFlag(0);
            entity.setCreateDate(sdf.format(new Date()));
        }
        return saveBatch(list);
    }

    @Override
    public boolean delFormAction(Long formId, Long actionId) {
        if(formId == null || formId == 0 ){
            throw new IllegalArgumentException("记录不存在");
        }
        if(actionId == null || actionId == 0 ){
            throw new IllegalArgumentException("记录不存在");
        }
        UpdateWrapper<SdFormActionConfEntity> updateWrapper = new UpdateWrapper();
        updateWrapper.set("DEL_FLAG",1).eq("FORM_ID",formId).eq("ACTION_ID",actionId);
        try {
            return update(updateWrapper);
        }catch (Exception e){
            log.error(ExceptionUtils.getStackTrace(e));
            return false;
        }
    }

    @Override
    public boolean updateFormAction(List<SdFormActionConfEntity> list) {
        UpdateWrapper<SdFormActionConfEntity> updateWrapper = new UpdateWrapper();
        try {
            for (SdFormActionConfEntity entity: list) {
                updateWrapper.set("DISPLAY_ORDER",entity.getDisplayOrder()).eq("FORM_ID",entity.getFormId()).eq("ACTION_ID",entity.getActionId());
                update(updateWrapper);
                updateWrapper.clear();
            }
            return true;
        }catch (Exception e){
            log.error(ExceptionUtils.getStackTrace(e));
            return false;
        }
    }

    @Override
    public boolean formRepoBind(SdFormConfigDto dto) {
        Map<String,Object> paramMap = new HashMap<>();
        Date date = new Date();
        SdFormFlowRepoBindEntity sdFormFlowRepoBindDto = new SdFormFlowRepoBindEntity();
        SdRepoLimitTimeEntity sdRepoLimitTimeDto = new SdRepoLimitTimeEntity();
        paramMap.put("businessTypeId",dto.getBusiType());
        paramMap.put("splitMode","XOR");
        paramMap.put("joinMode","XOR");
        paramMap.put("activateRuleType","directRunning");
        paramMap.put("finishType",dto.getBwpRepoFinishType());
        paramMap.put("invokePattern","synchronous");
        paramMap.put("transactionType","join");
        paramMap.put("exceptionStrategy","ignore");
        paramMap.put("executeAction","");
        paramMap.put("rollbackAction","");
        paramMap.put("triggerEvents",new Object[]{});
        paramMap.put("apiVersion",dto.getBwpRepoVersion());
        paramMap.put("apiCode",dto.getBwpRepoCode());
        paramMap.put("participantType","process-starter");
        paramMap.put("activityType",dto.getBwpRepoType());
        paramMap.put("isAllowAppointParticipants",true);
        paramMap.put("action",dto.getFlowFormRelaId());
        paramMap.put("activityName",dto.getBwpRepoName());
        paramMap.put("limitTime",sdRepoLimitTimeDto.getFinishTimeLimit());

        //创建环节
        R result = bwpOperDockingClient.createRepo(JSONObject.toJSONString(paramMap));
        if(result.getCode()!=200) {
            log.info("生成环节失败");
            throw new GlobalException("流程环节创建失败", 500);
        }
        Map<String,Object> resultMap = (Map)result.getData();
        try {
            //保存环节绑定
            sdFormFlowRepoBindDto.setBwpId((String) resultMap.get("id"));
            sdFormFlowRepoBindDto.setBwpRepoId((String) resultMap.get("repoId"));
            sdFormFlowRepoBindDto.setBwpProcessDefName("");
            sdFormFlowRepoBindDto.setBwpRepoVersion(dto.getBwpRepoVersion());
            sdFormFlowRepoBindDto.setFormId(dto.getFormId());
            sdFormFlowRepoBindDto.setBwpRepoCode(dto.getBwpRepoCode());
            sdFormFlowRepoBindDto.setBwpRepoFinishType(dto.getBwpRepoFinishType());
            sdFormFlowRepoBindDto.setBwpRepoName(dto.getBwpRepoName());
            sdFormFlowRepoBindDto.setBwpRepoType(dto.getBwpRepoType());
            sdFormFlowRepoBindDto.setBwpProcessDefName("");
            sdFormFlowRepoBindDto.setShardingId(0);
            this.baseMapper.saveFormFlowRepoBind(sdFormFlowRepoBindDto);

            //保存环节参与者
            List<SdRepoParticipantConfEntity> list = dto.getList();
            if (list.size() > 0){
                for (SdRepoParticipantConfEntity entity:list) {
                    entity.setActivityRepoId((String) resultMap.get("repoId"));
                    entity.setTaskSheetType(dto.getBusiType());
                    entity.setAreaId(0);
                }
                bwpOperDockingClient.saveParticipants(list);
                // sdParticipantConfService.batchSaveParticipant(list);
            }
            if (dto.getBwpRepoTimeLimit() != null){
                //保存环节时限
                sdRepoLimitTimeDto.setActivityRepoId((String) resultMap.get("repoId"));
                sdRepoLimitTimeDto.setProcessDefId("");
                sdRepoLimitTimeDto.setFinishTimeLimit(dto.getBwpRepoTimeLimit());
                sdRepoLimitTimeDto.setTaskSheetType(dto.getBusiType());
                sdRepoLimitTimeDto.setCreateDate(sdf.format(date));
                sdRepoLimitTimeDto.setAreaId(0);
                sdRepoLimitTimeDto.setDelFlag(0);
                sdRepoLimitTimeDto.setShardingId(0);
                sdRepoTimeLimitService.saveLimitTime(sdRepoLimitTimeDto);
            }
            return true;
        }catch (Exception e){
            log.error(ExceptionUtils.getStackTrace(e));
            return false;
        }

    }


    @Override
    public SdFormConfigDto queryFormRepoInfo(Long formId) {
        SdFormConfigDto sdFormConfigDto = this.baseMapper.queryFormRepoInfo(formId);
        if(sdFormConfigDto == null){
            return null;
        }
        R result = bwpOperDockingClient.queryParticipantsByRepoId(sdFormConfigDto.getBwpRepoId());
        if (result.getCode() != 200){
            throw new GlobalException("查询环节信息失败", 500);
        }
        List<SdRepoParticipantConfEntity> data = (List<SdRepoParticipantConfEntity>)result.getData();
        data = new ObjectMapper().convertValue(data, new TypeReference<List<SdRepoParticipantConfEntity>>() {
        });
        sdFormConfigDto.setList(data);
        String ids = "";
        if (data.size() > 0){
            for (SdRepoParticipantConfEntity entity:data) {
                ids += entity.getId() + "-";
            }
            ids.substring(0,ids.length()-1);
        }
        sdFormConfigDto.setParticipantConfIds(ids);
        return sdFormConfigDto;
    }


    @Override
    public boolean updateFormRepoBind(SdFormConfigDto dto) {
        Map<String,Object> paramMap = new HashMap<>();
        SdFormFlowRepoBindEntity sdFormFlowRepoBindDto = new SdFormFlowRepoBindEntity();
        SdRepoLimitTimeEntity sdRepoLimitTimeDto = new SdRepoLimitTimeEntity();
        paramMap.put("id",dto.getBwpId());
        paramMap.put("splitMode","XOR");
        paramMap.put("joinMode","XOR");
        paramMap.put("activateRuleType","directRunning");
        paramMap.put("finishType",dto.getBwpRepoFinishType());
        paramMap.put("invokePattern","synchronous");
        paramMap.put("transactionType","join");
        paramMap.put("exceptionStrategy","ignore");
        paramMap.put("executeAction","");
        paramMap.put("rollbackAction","");
        paramMap.put("triggerEvents",new Object[]{});
        paramMap.put("apiVersion",dto.getBwpRepoVersion());
        paramMap.put("participantType","process-starter");
        paramMap.put("activityType",dto.getBwpRepoType());
        paramMap.put("isAllowAppointParticipants",true);
        paramMap.put("action",dto.getFlowFormRelaId());
        paramMap.put("activityName",dto.getBwpRepoName());
        paramMap.put("limitTime",dto.getBwpRepoTimeLimit());
        //修改环节
        R result = bwpOperDockingClient.updateRepo(JSONObject.toJSONString(paramMap));
        if(result.getCode()==500){
            log.info("修改环节失败");
            throw new GlobalException("流程环节修改失败",500);
        }

        try {
            //更新环节绑定信息
            sdFormFlowRepoBindDto.setFormId(dto.getFormId());
            sdFormFlowRepoBindDto.setBwpRepoId(dto.getBwpRepoId());
            sdFormFlowRepoBindDto.setBwpRepoVersion(dto.getBwpRepoVersion());
            sdFormFlowRepoBindDto.setBwpRepoCode(dto.getBwpRepoCode());
            sdFormFlowRepoBindDto.setBwpRepoFinishType(dto.getBwpRepoFinishType());
            sdFormFlowRepoBindDto.setBwpRepoName(dto.getBwpRepoName());
            sdFormFlowRepoBindDto.setBwpRepoType(dto.getBwpRepoType());
            this.baseMapper.updateFormRepoByRepoId(sdFormFlowRepoBindDto);
            //更新环节参与者
            //先删除该环节配置的参与人
            //sdParticipantConfService.deleteParticipantByRepoId(dto.getBwpRepoId());
            if (StringUtils.isNotBlank(dto.getParticipantConfIds())){
                bwpOperDockingClient.delParticipantsById(dto.getParticipantConfIds());
            }
            List<SdRepoParticipantConfEntity> list = dto.getList();
            if (list.size() > 0){
                for (SdRepoParticipantConfEntity entity:list) {
                    entity.setActivityRepoId(dto.getBwpRepoId());
                    entity.setTaskSheetType(dto.getBusiType());
                    entity.setAreaId(0);
                }
                bwpOperDockingClient.saveParticipants(list);
                // sdParticipantConfService.batchSaveParticipant(list);
            }
            //更新环节时限
            SdRepoLimitTimeEntity repoLimitTimeEntity = sdRepoTimeLimitService.getById(dto.getBwpRepoId());
            if (repoLimitTimeEntity != null){
                sdRepoLimitTimeDto.setParticipantConfId(dto.getTimeLimitId());
                sdRepoLimitTimeDto.setFinishTimeLimit(dto.getBwpRepoTimeLimit());
                sdRepoTimeLimitService.updateLimitTime(sdRepoLimitTimeDto);
            }else {
                if (dto.getBwpRepoTimeLimit() != null){
                    //保存环节时限
                    Date date = new Date();
                    sdRepoLimitTimeDto.setActivityRepoId(dto.getBwpRepoId());
                    sdRepoLimitTimeDto.setProcessDefId("");
                    sdRepoLimitTimeDto.setFinishTimeLimit(dto.getBwpRepoTimeLimit());
                    sdRepoLimitTimeDto.setTaskSheetType(dto.getBusiType());
                    sdRepoLimitTimeDto.setCreateDate(sdf.format(date));
                    sdRepoLimitTimeDto.setAreaId(0);
                    sdRepoLimitTimeDto.setDelFlag(0);
                    sdRepoLimitTimeDto.setShardingId(0);
                    sdRepoTimeLimitService.saveLimitTime(sdRepoLimitTimeDto);
                }
            }

        }catch (Exception e){
            log.error(ExceptionUtils.getStackTrace(e));
            return false;
        }
        return true;
    }

    @Override
    public boolean deleteRepoBind(String repoId) {
        R result = bwpOperDockingClient.deleteRepo(repoId);
        if (result.getCode() != 200) {
            throw new GlobalException("删除环节失败",500);
        }
        try {
            this.baseMapper.deleteRepoByRepoId(repoId);
        }catch (Exception e){
            log.error("删除失败",e);
            return false;
        }
        return true;
    }
}
